package com.bwie.service.impl;

import cn.hutool.core.lang.Validator;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.crypto.digest.DigestUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bwie.pojo.TbMenu;
import com.bwie.pojo.TbUser;
import com.bwie.service.TbUserService;
import com.bwie.mapper.TbUserMapper;
import com.bwie.utils.MobileMessageUtil;
import com.bwie.utils.Result;
import com.bwie.utils.TokenUtils;
import com.bwie.vo.LoginVo;
import com.bwie.vo.MobileVo;
import com.bwie.vo.PageInfoVo;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @author lenovo
 * @description 针对表【tb_user(用户表)】的数据库操作Service实现
 * @createDate 2025-06-19 09:39:57
 */
@Service
public class TbUserServiceImpl extends ServiceImpl<TbUserMapper, TbUser>
        implements TbUserService {
    @Autowired
    TbUserMapper tbUserMapper;
    @Autowired
    StringRedisTemplate stringRedisTemplate;

    @Autowired
    HttpServletRequest request;

    @Override
    public Result accountLogin(LoginVo loginVo) {
        //获取用户信息
        TbUser tbUser = tbUserMapper.selectOne(
                new QueryWrapper<TbUser>().lambda().eq(TbUser::getUserName, loginVo.getUserName())
        );
        //判断用户是否存在
        if (tbUser == null) {
            return Result.error().setMsg("用户不存在");
        }
        //密码加密
        String md5Hex = DigestUtil.md5Hex(loginVo.getUserPass());
        System.out.println("加密后密码" + md5Hex);
        //判断密码是否正确
        if (!tbUser.getUserPass().equals(md5Hex)) {
            return Result.error().setMsg("密码错误");
        }
        //生成token
        String token = Jwts.builder().signWith(SignatureAlgorithm.HS256, "123456")
                .claim("userId", tbUser.getUserId())
                .claim("userName", tbUser.getUserName())
                .compact();
        String key = "token-" + tbUser.getUserId();
        //存入缓存
        stringRedisTemplate.opsForValue().set(key, token, 60, TimeUnit.MINUTES);
        tbUser.setToken(token);
        tbUser.setUserPass(null);
        return Result.ok().setData(tbUser);
    }

    @Override
    public Result sendCode(String mobile) {
        //校验手机号格式是否正确
        if (!Validator.isMobile(mobile)) {
            return Result.error().setMsg("手机号格式不正确");
        }

//        String send = "send" + mobile;

        Boolean hasKey = stringRedisTemplate.hasKey("send");
        if (hasKey) {
            return Result.error().setMsg("一分钟只能发一次");
        }

        TbUser tbUser = tbUserMapper.selectOne(
                new QueryWrapper<TbUser>().lambda().eq(TbUser::getUserMobile, mobile)
        );
        if (tbUser == null) {
            //手机号不存在 创建用户
            tbUser = new TbUser();
            tbUser.setUserMobile(mobile);
            tbUserMapper.insert(tbUser);
        }
        //生成验证码
        String code = RandomUtil.randomNumbers(4);
        System.out.println("验证码" + code);

        //存入缓存
        String key = "login-" + mobile;

        stringRedisTemplate.opsForValue().set(key, code, 5, TimeUnit.MINUTES);

        stringRedisTemplate.opsForValue().set("send", code, 1, TimeUnit.MINUTES);

        //发送验证码
        MobileMessageUtil.sendMobileMessage(mobile, code);
        return Result.ok().setData(code);
    }

    @Override
    public Result mobileLogin(MobileVo mobileVo) {
        String key = "login-" + mobileVo.getMobile();
        String redisKey = stringRedisTemplate.opsForValue().get(key);
        if (redisKey == null) {
            return Result.error().setMsg("验证码已过期");
        }
        if (!redisKey.equals(mobileVo.getCode())) {
            return Result.error().setMsg("验证码错误");
        }
        //获取用户信息
        TbUser tbUser = tbUserMapper.selectOne(
                new QueryWrapper<TbUser>().lambda().eq(TbUser::getUserMobile, mobileVo.getMobile())
        );
        if (tbUser == null) {
            return Result.error().setMsg("用户名不存在");
        }
        //生成token
        String token = Jwts.builder().signWith(SignatureAlgorithm.HS256, "123456")
                .claim("userId", tbUser.getUserId())
                .claim("userMobile", tbUser.getUserMobile())
                .compact();
        //缓存redis
        String keyToken = "token-" + tbUser.getUserId();
        stringRedisTemplate.opsForValue().set(keyToken, token);
        tbUser.setToken(token);
        return Result.ok().setData(tbUser);
    }

    @Override
    public Result getMenuTree() {
        //从token中解析出来userId
        String token = request.getHeader("token");
        if (token == null) {
            return Result.error().setMsg("请先登录");
        }
        Integer userId = TokenUtils.tokenUtils(token);
        //根据用户ID获取权限列表
        List<TbMenu> menuList = tbUserMapper.getMenuListByUserId(userId);
        //把用户的权限封装到菜单树
        List<Tree<String>> treeList = TreeUtil.build(menuList, "0", (menu, tree) -> {
            tree.setId(menu.getMenuId() + "");
            tree.setParentId(menu.getMenuPid() + "");
            tree.setName(menu.getMenuName());
            tree.putExtra("menuPath", menu.getMenuPath());

        });
        return Result.ok().setData(treeList);
    }

    @Override
    public Result getUserList(PageInfoVo pageInfoVo) {
        //构造分页参数
        Page<TbUser> page = new Page<>(pageInfoVo.getPageNum(), pageInfoVo.getPageSize());
        //获取用户列表
        QueryWrapper<TbUser> wrapper = new QueryWrapper<>();
        wrapper.lambda().orderByDesc(TbUser::getUserId);
        Page<TbUser> userPage = tbUserMapper.selectPage(page, wrapper);
        //返回用户列表
        return Result.ok().setData(userPage);
    }
}




